﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace pogra
{
    /// <summary>
    /// An extended version of the SpriteBatch class that supports line and
    /// rectangle drawing.
    /// </summary>
    public class ExtendedSpriteBatch : SpriteBatch
    {
        /// <summary>
        /// The texture used when drawing rectangles, lines and other 
        /// primitives. This is a 1x1 white texture created at runtime.
        /// </summary>
        public Texture2D WhiteTexture { get; protected set; }

        public ExtendedSpriteBatch(GraphicsDevice graphicsDevice)
            : base(graphicsDevice)
        {
            this.WhiteTexture = new Texture2D(this.GraphicsDevice, 1, 1);
            this.WhiteTexture.SetData(new Color[] { Color.White });
        }

        /// <summary>
        /// Draw a line between the two supplied points.
        /// </summary>
        /// <param name="start">Starting point.</param>
        /// <param name="end">End point.</param>
        /// <param name="color">The draw color.</param>
        public void DrawLine(Vector2 start, Vector2 end, Color color, int width = 2)
        {
            float length = (end - start).Length();
            float rotation = (float)Math.Atan2(end.Y - start.Y, end.X - start.X);
            this.Draw(this.WhiteTexture, start, null, color, rotation, Vector2.Zero, new Vector2(length, width), SpriteEffects.None, 0);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="centre"></param>
        /// <param name="r"></param>
        /// <param name="w"></param>
        /// <param name="range"></param>
        public void DrawCircle(Vector2 centre, int r, float w, Color color, double range = Math.PI *2)
        {
                int outerRadius = r*2 + 2; // So circle doesn't go out of bounds
                Texture2D texture = new Texture2D(GraphicsDevice, outerRadius, outerRadius);

                Color[] data = new Color[outerRadius * outerRadius];

                // Colour the entire texture transparent first.
                for (int i = 0; i < data.Length; i++)
                    data[i] = Color.Transparent;

                // Work out the minimum step necessary using trigonometry + sine approximation.
                double angleStep = 1f / r;

                double tmp1, tmp2;
                int x1, x2, y1, y2;

                for (double angle = 0; angle < range; angle += angleStep)
                {
                    tmp1 = Math.Cos(angle - Math.PI / 2);
                    tmp2 = Math.Sin(angle - Math.PI / 2);

                    x1 = (int)Math.Round(r + r * tmp1);
                    y1 = (int)Math.Round(r + r * tmp2);

                    x2 = (int)Math.Round(r + (r-1) * tmp1);
                    y2 = (int)Math.Round(r + (r-1) * tmp2);

                    data[y1 * outerRadius + x1 +1 ] = Color.White; 
                    data[y2 * outerRadius + x2 + 1] = Color.White;

                    
                }

                texture.SetData(data);
                //this.Draw(texture,centre - new Vector2((float)r,(float)r),null,color,0f,Vector2.Zero,SpriteEffects.None);
                this.Draw(texture, centre, null, color, 0, new Vector2(texture.Width, texture.Height) / 2, 1, SpriteEffects.None, 0.999f);
                
        }
        /// <summary>
        /// Draw a rectangle.
        /// </summary>
        /// <param name="rectangle">The rectangle to draw.</param>
        /// <param name="color">The draw color.</param>
        public void DrawRectangle(Rectangle rectangle, Color color, int width = 1)
        { 
            #region obsługa ujemnych wymiarów
            // dopisałem tutaj, żeby można było rysować prostokąty o ujemnych wysokościach i szerokościach. jf
            if (rectangle.Height < 0)
            {
                rectangle.Y += rectangle.Height;
                rectangle.Height = -rectangle.Height;
            }

            if (rectangle.Width < 0)
            {
                rectangle.X += rectangle.Width;
                rectangle.Width = -rectangle.Width;
            }
            #endregion

            this.Draw(this.WhiteTexture, new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, width), color);
            this.Draw(this.WhiteTexture, new Rectangle(rectangle.Left, rectangle.Bottom, rectangle.Width, width), color);
            this.Draw(this.WhiteTexture, new Rectangle(rectangle.Left, rectangle.Top, width, rectangle.Height), color);
            this.Draw(this.WhiteTexture, new Rectangle(rectangle.Right, rectangle.Top, width, rectangle.Height + width), color);
        }

        /// <summary>
        /// Fill a rectangle.
        /// </summary>
        /// <param name="rectangle">The rectangle to fill.</param>
        /// <param name="color">The fill color.</param>
        public void FillRectangle(Rectangle rectangle, Color color,float layer = 0.001f)
        {
           // this.Draw(this.WhiteTexture, rectangle, color);
            this.Draw(this.WhiteTexture, rectangle, null, color, 0, Vector2.Zero, SpriteEffects.None, layer);   
        }
    }
}